package com.yonyou.pmclouds.outter.user;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yonyou.iuap.tenant.sdk.UserCenter;
import com.yonyou.pmclouds.basecom.conf.DeployTypeConfiguration;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.runtime.RuntimeEnvironment;
import com.yonyou.pmclouds.basecom.util.BeanHelper;
import com.yonyou.pmclouds.basecom.util.ChineseStringUtils;
import com.yonyou.pmclouds.basecom.util.CommonProgramConsts;
import com.yonyou.pmclouds.businessobject.util.SortListUtil;
import com.yonyou.pmclouds.enterprise.entity.EnterpriseInfo;
import com.yonyou.pmclouds.outter.enterprise.EnterpriseInfoQuery;
import com.yonyou.pmclouds.outter.tenant.TenantInfoQuery;
import com.yonyou.pmclouds.user.entity.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * 用户中心相关查询
 * <br>
 * 参阅 <a href="http://172.16.50.96/pages/viewpage.action?pageId=82719191">租户用户相关的sdk</a>
 * <br>和<a href="http://172.16.50.96/pages/viewpage.action?pageId=84188946">获取用户信息</a>
 */
@Slf4j
@Component
public class UserInfoQuery {
    @Autowired
    private TenantInfoQuery query;
    @Autowired
    private EnterpriseInfoQuery enterpriseInfoQuery;
    //TODO 需要cache来处理
    private ObjectMapper jsonMapper;

    public UserInfoQuery() {
        jsonMapper = new ObjectMapper();
        // 设置反序列化时忽略vo中不存在的字段，放置平台偷偷的加字段，导致异常
        jsonMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    public String queryUserName(String id) {
        UserInfo user = queryUser(id);
        if (user != null)
            return user.getUserName();
        return null;
    }

    public UserInfo queryUser(String id) {
        UserInfo[] result = queryUsers(new String[]{id});
        if (!ArrayUtils.isEmpty(result)) {
            return result[0];
        }
        return null;
    }

    public UserInfo[] queryUsers(String[] ids) {
        String userInfos = UserCenter.getUsersByUserIds(Arrays.asList(ids));
        UserBatchQueryVO userBatchQueryVO = null;
        if (StringUtils.isEmpty(userInfos)) {
            return null;
        }
        try {
            userBatchQueryVO = jsonMapper.readValue(userInfos, UserBatchQueryVO.class);
        } catch (IOException e) {
            return null;
        }
        if (userBatchQueryVO != null) {
            return userBatchQueryVO.getUsers();
        }
        return null;
    }

    public Map<String, String> queryUserNames(String[] ids) {
        UserInfo[] t = queryUsers(ids);
        if (!ArrayUtils.isEmpty(t)) {
            Map<String, String> result = new HashMap<>(t.length);
            for (UserInfo user : t) {
                UserInfo u = user;
                if (u != null) {
                    result.put(u.getUserId(), u.getUserName());
                }
            }
            return result;
        }
        return new HashMap<>();
    }

    public UserSearchResultVO.ContentVO searchUserInSystem(String tenantid, String keyword, int pageNum,
                                                           int pageSize, String[] excludeUsers) {
        if (pageNum > CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE) {
            pageNum = CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE;
        }
        //  添加系统id
        String result;
        if (query.isTenantUserAutoToSystem(tenantid, DeployTypeConfiguration.getSysId())) {
            result = UserCenter.searchUserListNotInUserIds(tenantid, Integer.toString(pageSize),
                    Integer.toString(pageNum), keyword, "userName", Arrays.asList(excludeUsers));
        } else {
            result = UserCenter.searchAppUserListNotInUserIds(tenantid, DeployTypeConfiguration.getSysId(), Integer.toString(pageSize),
                    Integer.toString(pageNum), keyword, "userName", Arrays.asList(excludeUsers));
        }
        if (StringUtils.isEmpty(result)) {
            return new UserSearchResultVO.ContentVO();
        }
        try {
            UserSearchResultVO resultVO = jsonMapper.readValue(result, UserSearchResultVO.class);
            if (resultVO != null && resultVO.getStatus() == 1) {
                return resultVO.getUsers();
            }
        } catch (IOException e) {
            return new UserSearchResultVO.ContentVO();
        }
        return new UserSearchResultVO.ContentVO();

    }

    public UserSearchResultVO.ContentVO searchUsers(String tenantid, String keyword, int pageNum,
                                                           int pageSize) {
        if (pageNum > CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE) {
            pageNum = CommonProgramConsts.DEFAULT_MAX_QUERY_SIZE;
        }
        //  添加系统id
        String result;
//        if (query.isTenantUserAutoToSystem(tenantid, DeployTypeConfiguration.getSysId())) {
//            result = UserCenter.searchUserList(tenantid, Integer.toString(pageSize),
//                    Integer.toString(pageNum), keyword, "userName");
//        } else {
//            result = UserCenter.searchAppUserList(tenantid, DeployTypeConfiguration.getSysId(), Integer.toString(pageSize),
//                    Integer.toString(pageNum), keyword, "userName");
//        }
        // UserCenter.searchAppUserList方法有问题，故不判断用户是否同步，升级友互通版本时再调整
        result = UserCenter.searchUserList(tenantid, Integer.toString(pageSize),
                Integer.toString(pageNum), keyword, "userName");

        if (StringUtils.isEmpty(result)) {
            return new UserSearchResultVO.ContentVO();
        }
        try {
            UserSearchResultVO resultVO = jsonMapper.readValue(result, UserSearchResultVO.class);
            if (resultVO != null && resultVO.getStatus() == 1) {
                return resultVO.getUsers();
            }
        } catch (IOException e) {
            return new UserSearchResultVO.ContentVO();
        }
        return new UserSearchResultVO.ContentVO();

    }

    public Map<String, UserInfo> extractUserInfoFromBeans(Object[] beans, String[] userIdFields) {
        if (ArrayUtils.isEmpty(beans)) {
            return new HashMap<>();
        }
        Set<String> userIds = new HashSet<>();
        for (String userIdField : userIdFields) {
            Method read = BeanHelper.getGetMethod(beans[0], userIdField);
            if (read == null) {
                continue;
            }
            for (Object src : beans) {
                try {
                    String id = (String) read.invoke(src);
                    userIds.add(id);
                } catch (Exception e) {
                    log.error("read userid error {}", read);
                }
            }
        }
        UserInfo[] users = queryUsers(userIds.toArray(new String[userIds.size()]));
        if (ArrayUtils.isEmpty(users)) {
            return new HashMap<>();
        }
        Map<String, UserInfo> result = new HashMap<>(users.length);
        for (UserInfo user : users) {
            result.put(user.getUserId(), user);
        }
        return result;
    }

    public void tranUserInfoField(Object[] beans, String[] userIdFields, String[] userNameFields) {
        tranUserInfoField(beans, beans, userIdFields, userNameFields);
    }

    public void tranUserInfoField(Object[] srcs, Object[] dests,
                                  String[] userIdFields, String[] userNameFields) {
        if (ArrayUtils.isEmpty(srcs) || ArrayUtils.isEmpty(dests) || srcs.length != dests.length) {
            return;
        }
        Set<String> userIds = new HashSet<>();
        for (String userIdField : userIdFields) {
            Method read = BeanHelper.getGetMethod(srcs[0], userIdField);
            if (read == null) {
                continue;
            }
            for (Object src : srcs) {
                try {
                    String id = (String) read.invoke(src);
                    userIds.add(id);
                } catch (Exception e) {
                    log.error("read userid error {}", read);
                }
            }
        }
        Map<String, String> userIdNameMap = queryUserNames(userIds.toArray(new String[userIds.size()]));
        for (int i = 0; i < userIdFields.length; i++) {
            Method write = BeanHelper.getSetMethod(dests[0], userNameFields[i]);
            Method read = BeanHelper.getGetMethod(srcs[0], userIdFields[i]);
            if (write == null) {
                continue;
            }
            for (int j = 0; j < srcs.length; j++) {
                try {
                    write.invoke(dests[j], userIdNameMap.get(read.invoke(srcs[j])));
                } catch (Exception e) {
                    log.error("write userid error {}", write);
                }
            }
        }
    }
    
    public static String CONTACT_MOBILE = "mobile";
    public static String CONTACT_EMAIL = "email";

    /**
     *
     * 方法功能描述：根据联系方式获取用户ID。
     *
     * <b>参数说明</b>
     * @param mobile
     * @param email
     * @return
     * @throws BusinessException
     * @author zhangwce
     * @time 2018年1月25日 下午10:39:40
     */
    public UserInfo getUserIdByContact(String mobile, String email) throws BusinessException {

        if(StringUtils.isEmpty(mobile) &&  StringUtils.isEmpty(email))
            return null;

        UserInfo[] userInfos = null;
        if(!StringUtils.isEmpty(mobile)){
            userInfos = getUserByContact(mobile, CONTACT_MOBILE);
        }else if(!StringUtils.isEmpty(email)){
            userInfos =  getUserByContact(email, CONTACT_EMAIL);
        }

        if(userInfos == null || userInfos.length == 0)
            return null;
          return userInfos[0];
    }

    public UserSearchResultVO.ContentVO searchUsersByEnterId(String keyword, String enterid, int pageNum, int pageSize, String[] excludeUser){
        if (pageSize < CommonProgramConsts.DEFAULT_MIN_QUERY_SIZE) {
            pageSize = CommonProgramConsts.DEFAULT_MIN_QUERY_SIZE;
        }

        EnterpriseUserResultVO enterpriseUserResultVO = enterpriseInfoQuery.searchEnterUserById(enterid, keyword, pageNum, pageSize);

        UserSearchResultVO.ContentVO contentVO = new UserSearchResultVO.ContentVO();

        if(enterpriseUserResultVO == null){
            return contentVO;
        }
        contentVO.setPageNo(pageNum);
        contentVO.setTotalElements(enterpriseUserResultVO.getTotalNumber());
        int totalPages = enterpriseUserResultVO.getTotalNumber() / pageSize;
        if(enterpriseUserResultVO.getTotalNumber() % pageSize > 0){
            totalPages ++;
        }
        contentVO.setTotalPages(totalPages);
        contentVO.setNumberOfElements(pageSize);

        List<EnterpriseUserVO> enterpriseUserVOS = enterpriseUserResultVO.getData();

        if(enterpriseUserVOS == null || enterpriseUserVOS.size() <= 0){
            contentVO.setLast(true);
            contentVO.setLastPage(true);
        }else{
            contentVO.setLast(false);
            contentVO.setLastPage(false);
        }

        if(pageNum == 1){
            contentVO.setFirst(true);
            contentVO.setFirstPage(true);
        }else {
            contentVO.setFirst(false);
            contentVO.setFirstPage(false);
        }

        Map<String, String> excludeUserMap = new HashMap<>();
        if(excludeUser != null && excludeUser.length > 0){
            for(String excludeUserTemp : excludeUser){
                excludeUserMap.put(excludeUserTemp, excludeUserTemp);
            }
        }

        if(enterpriseUserVOS != null && enterpriseUserVOS.size() > 0){
            SortListUtil.sort(enterpriseUserVOS, "userName", "ase");

            List<UserInfo> userInfoList = new ArrayList<>();
            for (EnterpriseUserVO enterpriseUserVO : enterpriseUserVOS) {
                if (StringUtils.isNotEmpty(excludeUserMap.get(enterpriseUserVO.getUserId()))) {
                    continue;
                }

                UserInfo userInfo = new UserInfo();
                userInfo.setUserId(enterpriseUserVO.getUserId());
                userInfo.setDefaultEntId(enterpriseUserVO.getEnterId());
                userInfo.setDefaultEntName(enterpriseUserVO.getEnterName());
                userInfo.setUserMobile(enterpriseUserVO.getUserMobile());
                userInfo.setUserEmail(enterpriseUserVO.getUserEmail());
                userInfo.setUserName(enterpriseUserVO.getUserName());
                userInfo.setUserCode(enterpriseUserVO.getUserCode());
                userInfoList.add(userInfo);
            }

            contentVO.setContent(userInfoList.toArray(new UserInfo[]{}));
        }

        return contentVO;
    }

    public UserSearchResultVO.ContentVO searchUsers(String keyword, String enterid, int pageNum, int pageSize, String[] excludeUser) throws BusinessException {

        if (pageSize < CommonProgramConsts.DEFAULT_MIN_QUERY_SIZE) {
            pageSize = CommonProgramConsts.DEFAULT_MIN_QUERY_SIZE;
        }

        List<UserInfo> finalResult = new ArrayList<>(pageSize << 2);
        UserSearchResultVO.ContentVO result = null;
        int page = pageNum - 1;
        int allowedNum = pageSize >> 1; // 允许的比pageSize小的页码
        do {
            page++;
            result = this.searchUserInSystem(RuntimeEnvironment.getTenantId(), keyword, page, pageSize, excludeUser);
            UserInfo[] infos = result.getContent();
            if (ArrayUtils.isEmpty(infos)) {
                continue;
            }
            String[] userids = new String[infos.length];
            // 抽取用户id，查询企业信息
            for (int i = 0; i < userids.length; i++) {
                userids[i] = infos[i].getUserId();
            }
            Map<String, EnterpriseInfo[]> entUserMap = enterpriseInfoQuery.getEnterprisesOfUsers(userids);
            for (UserInfo info : infos) {
                EnterpriseInfo[] ents = entUserMap.get(info.getUserId());
                if (ArrayUtils.isEmpty(ents)) {
                    continue;
                }
                for (EnterpriseInfo ent : ents) {
                    if (enterid.equals(ent.getId())) {
                        // 设置企业信息
                        info.setDefaultEntId(ent.getId());
                        info.setDefaultEntName(ent.getName());
                        finalResult.add(info);
                        break;
                    }
                }
            }
            if (ArrayUtils.isEmpty(result.getContent())) {
                result.setLast(true);
                result.setLastPage(true);
            }
        }
        while (result != null && !result.isLastPage() && !ArrayUtils.isEmpty(result.getContent()) && pageSize - finalResult.size() >= allowedNum);
        // 循环去取新的，直到数据量差不多
        UserInfo[] userInfos = finalResult.toArray(new UserInfo[finalResult.size()]);

        Arrays.sort(userInfos, new Comparator<UserInfo>() {
            @Override
            public int compare(UserInfo o1, UserInfo o2) {
                if (o1 == o2) {
                    return 0;
                }
                if (o1 == null) {
                    return 1;
                }
                if (o2 == null) {
                    return -1;
                }

                return ChineseStringUtils.compareInDict(o1.getUserName(), o2.getUserName());

            }
        });


        result.setContent(userInfos);
        result.setPageNo(page);
        return result;
    }
    private UserInfo[] getUserByContact(String contact, String method) throws BusinessException{
    	
    	if(contact == null)
    		return null;
    	
    	String userInfo = null;
		if(CONTACT_MOBILE.equals(method)){
			userInfo = UserCenter.getUserByContact(contact, "mobile");
		}else if(CONTACT_EMAIL.equals(method)){
			userInfo = UserCenter.getUserByContact(contact, "email");
		}

        UserBatchQueryVO userBatchQueryVO = null;
		try {
            userBatchQueryVO = jsonMapper.readValue(userInfo, UserBatchQueryVO.class);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		if(Integer.valueOf(0).equals(userBatchQueryVO.getStatus())){
			log.error("根据联系方式获取用户出错");
			throw new BusinessException("根据联系方式获取用户出错");
		}

        UserInfo[] userInfos = userBatchQueryVO.getUsers();
		return userInfos;
    }

    public String queryUserByCode(String userCode){
        String result = UserCenter.getUserByCode(userCode);

        Map<String,Object> resultMap = null;
        try {
            resultMap = jsonMapper.readValue(result, Map.class);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            return null;
        }

        if(resultMap == null)
            return null;

        if (resultMap != null)
            return  (String)resultMap.get("userId");
        return null;
    }

}
